
const RabbitMQ_Class=require("./rabbitmq/RabbitMq.js")
const readline = require('readline');
// const request = require('request');
const fs = require('fs');
const fse = require('fs-extra')
const path = require("path");
const {S3} = require('@aws-sdk/client-s3');
const { NodeHttpHandler } = require('@smithy/node-http-handler');
const http = require("http");
const  iconvLite = require('iconv-lite');
const twentyFiveMB = 25 * 1024 * 1024;
const maxSockets = 50;
const {spawn,exec,execSync,spawnSync,fork} = require('child_process');
Date.prototype.format = function (format, options) {
  var args = {
    "M+": this.getMonth() + 1,
    "d+": this.getDate(),
    "h+": this.getHours(),
    "m+": this.getMinutes(),
    "s+": this.getSeconds(),
    "q+": Math.floor((this.getMonth() + 3) / 3), //quarter
    S: this.getMilliseconds()
  };
  if (/(y+)/.test(format))
    format = format.replace(
      RegExp.$1,
      (this.getFullYear() + "").substr(4 - RegExp.$1.length)
    );
  for (var i in args) {
    var n = args[i];
    if (new RegExp("(" + i + ")").test(format))
      format = format.replace(
        RegExp.$1,
        RegExp.$1.length == 1 ? n : ("00" + n).substr(("" + n).length)
      );
  }
  return format;
}
class Help{
  static Json_Parse(Split) {
    try {
      Split = JSON.parse(Split);
      return Split;
    } catch (e) {
      return null;
    }
  }
  static Json_String(Split) {
    return JSON.stringify(Split);
  }
  static Check_isdir(_dir){
    if(fs.existsSync(_dir)){
      try{
        let stats=fs.statSync(_dir);
        if(stats.isDirectory()){
          return true
        }
      }
      catch(error){

      }
    }
    return false
  }
  static Check_isFile(_file){
    if(fs.existsSync(_file)){
      try{
        let stats=fs.statSync(_file);
        if(stats.isFile()){
          return true
        }
      }
      catch(error){

      }
    }
    return false
  }
  static async  Init_RabbitMQ(){
    let RabbitMQ=global["json_config"]?.RabbitMQ
    let _rabbitmq_Class= new RabbitMQ_Class({
      protocol: 'amqp',
      hostname: RabbitMQ.hostname,
      port: RabbitMQ.port,
      username: RabbitMQ.username,
      password: RabbitMQ.password,
      locale: 'en_US',
      frameMax: 0,
      heartbeat: 0,
      vhost: '/',
    })
    for(let a in RabbitMQ.queues){
      await _rabbitmq_Class.CheckQueue(RabbitMQ.queues[a])
      Help.Console_log(`connect Queue ${RabbitMQ.queues[a]} in process ${process.pid}`)
    }
    global["class_rabbitmq"]=_rabbitmq_Class
    return true
  }
  static async  Init_S3(){
    let config_s3=global["json_config"]?.s3
    if(!global["class_s3"]){
      global["class_s3"]=new S3({ 
        endpoint:config_s3?.endpoint,
        forcePathStyle: true,
        region:'us-east-1',
        credentials:{
          accessKeyId:config_s3?.accessKeyId, 
          secretAccessKey:config_s3?.secretAccessKey, 
        },
        requestHandler: new NodeHttpHandler({
          httpAgent: new http.Agent({
            maxSockets: maxSockets,
            keepAlive:true,
          })
        })
      });
    }
    return true
  }
  static s3_delete_file(options) {
    let {bucket,key}=options
    return new Promise(async (resolve)=>{
      global["class_s3"]?.deleteObject({
        Bucket:bucket, 
        Key:key
      },async (err, data)=>{
        if(!err){
          resolve(true)
        }
        else{
          resolve(false)
        }
      })
    })
  }
  static s3_multipartupload_file(options){
    return new Promise(async (resolve)=>{
      let {bucket,key,filename}=options
      let upload_file_stat=fs.statSync(filename);
      let upload_file_stat_size=upload_file_stat.size
      let multipartUpload=await global["class_s3"]?.createMultipartUpload({
        Bucket:bucket,
        Key:key,
      })
      let uploadId = multipartUpload.UploadId;
      let uploadPromises = [];
      let upload_file_id=fs.openSync(filename,'r');
      let Parts=Math.ceil(upload_file_stat_size / twentyFiveMB);
      //12 0-5 5-10 10-15 10-12
      for (let i = 0; i < Parts; i++) {
        let start = i * twentyFiveMB;
        let end = start + twentyFiveMB;
        if(end>upload_file_stat_size){
          end=upload_file_stat_size
        }
        let buffer=Buffer.alloc(end-start);
        fs.readSync(upload_file_id, buffer, 0, end-start, start);
        let one_uploadPart=global["class_s3"]?.uploadPart({
          Bucket: bucket,
          Key: key,
          UploadId: uploadId,
          Body: buffer,//subarray 
          PartNumber: i + 1,
        })
        uploadPromises.push(one_uploadPart);
      }
      fs.closeSync(upload_file_id);
      // let PromiseParts=Math.ceil(uploadPromises?.length / socketCapacity);
      // let uploadPromises_arrar=[]
      // for (let i = 0; i < PromiseParts;i++) {
      //   let start = i* socketCapacity;
      //   let end = start + socketCapacity;
      //   if(end>uploadPromises?.length){
      //     end=uploadPromises?.length
      //   }
      //   let this_uploadPromises=uploadPromises.slice(start,end)
      //   uploadPromises_arrar.push(this_uploadPromises)
      // }
      // let all_Promise_Parts=[]
      // for (let i = 0; i < PromiseParts;i++) {
      //   let one_uploadPromises=uploadPromises_arrar[i]
      //   
      //   let uploadResults_Parts=uploadResults.map(({ ETag }, j) => ({ETag,PartNumber: i*socketCapacity+j + 1,}))
      //   all_Promise_Parts=all_Promise_Parts.concat(uploadResults_Parts)
      // }
      let uploadResults = await Promise.all(uploadPromises);
      let uploadResults_Parts=uploadResults.map(({ ETag }, j) => ({ETag,PartNumber: j + 1,}))
      await global["class_s3"].completeMultipartUpload({
        Bucket: bucket,
        Key: key,
        UploadId: uploadId,
        MultipartUpload: {
          Parts: uploadResults_Parts,
        },
      })
      resolve(true)
    })
  }
  static  set_global_consume_exes(){
    global["consume_exes"]={}
    global["consume_exes"]["gdal_tile"]=`${global["json_config"]?.gdal_dir}/tile `
    global["consume_exes"]["gdaladdo"]=`${global["json_config"]?.gdal_dir}/gdaladdo`
    global["consume_exes"]["gdal_translate"]=`${global["json_config"]?.gdal_dir}/gdal_translate`
  }
  static async consume_rabbitmq(){
    Help.set_global_consume_exes()
    Help.consume_rabbitmq_tif_check_bandcount()
    Help.consume_rabbitmq_tif_convert()
    Help.consume_rabbitmq_tif_ovr()
    Help.consume_rabbitmq_tif_cog()
    Help.consume_rabbitmq_tif_upload()
    return true
  }
  static  consume_rabbitmq_tif_check_bandcount(){
    global["class_rabbitmq"].consume("tif_check_bandcount",async (data,msg)=>{
      let Json_data=Help.Json_Parse(data);
      let {src}=Json_data
      let band_count_txt=`${global["json_config"]?.produce_base_dir}/band_count.txt`
      Help.Del_File(band_count_txt);
      let run_parmars=["get_raster_bandcount",src,band_count_txt]
      if(global["json_config"]?.show_cmd===true){
        Help.Console_log(`波段确认:${global["consume_exes"]["gdal_tile"]} ${run_parmars.join(" ")}`)
      }
      let logs="";
      let bool_result=await Help.run_exe(global["consume_exes"]["gdal_tile"],run_parmars,(_data,error)=>{
        logs=logs+_data
      })
      if(logs){
        Help.Console_log(logs)
      }
      let band_count=-1;
      if(bool_result){
        if(Help.Check_isFile(band_count_txt)){
          band_count=Help.Read_File_UTF8(band_count_txt)
          band_count=band_count-0
          Help.Del_File(band_count_txt);
        }
      }
      if(band_count>=4){
        await Help.add_rabbitmq({
          src:src,
          inbands:"0,1,2",
          outbands:"2,1,0",
          do_ovr:true,
          do_cog:true,
          do_upload:true,
        },"tif_convert")
      }
      await global["class_rabbitmq"].ack(msg)
    });
    return true
  }
  static  consume_rabbitmq_tif_convert(){
    global["class_rabbitmq"].consume("tif_convert",async (data,msg)=>{
      let Json_data=Help.Json_Parse(data);
      let {src,savedir,inbands,outbands,do_ovr,do_cog,do_upload}=Json_data
      let denst_dir=`${global["json_config"]?.produce_base_dir}/chang_bands`
      Help.Create_Dir(denst_dir)
      let file_name="";
      if(src.indexOf("s3@")>=0){
        let split_names=src.split("@")
        let s3_key=split_names[1]
        s3_key=s3_key.replaceAll("\\","/")
        let s3_key_splits=s3_key.split("/")
        file_name=s3_key_splits[s3_key_splits.length-1]
      }
      else{
        src=src?.replaceAll("\\","/")
        src=src?.replaceAll(global["json_config"]?.W_L?.Windows_NT,global["json_config"]?.W_L?.Linux)
        if(!Help.Check_isFile(src)){
          await global["class_rabbitmq"].ack(msg)
          return 
        }
        file_name=Help.Get_FileName(src)
      }
      savedir=savedir?.replaceAll("\\","/")
      savedir=savedir?.replaceAll(global["json_config"]?.W_L?.Windows_NT,global["json_config"]?.W_L?.Linux)
      let denst_file="";
      if(Help.Check_isdir(savedir)){
        denst_file=`${savedir}/${file_name}`.toLocaleLowerCase()
      }
      else{
        denst_file=`${denst_dir}/${file_name}`.toLocaleLowerCase()
      }
      Help.Del_File(denst_file);
      let run_parmars=["copy_deep_raster",src,denst_file,inbands,outbands]
      if(global["json_config"]?.show_cmd===true){
        Help.Console_log(`波段转换:${global["consume_exes"]["gdal_tile"]} ${run_parmars.join(" ")}`)
      }
      let logs="";
      let bool_result=await Help.run_exe(global["consume_exes"]["gdal_tile"],run_parmars,(_data,error)=>{
        logs=logs+_data
      })
      if(logs){
        Help.Console_log(logs)
      }
      if(bool_result){
        await Help.add_rabbitmq({
          src:denst_file,
          old_src:src,
          savedir,
          do_ovr,
          do_cog,
          do_upload
        },"tif_ovr")
      }
      await global["class_rabbitmq"].ack(msg)
    });
    return true
  }
  static  consume_rabbitmq_tif_ovr(){
    global["class_rabbitmq"].consume("tif_ovr",async (data,msg)=>{
      let Json_data=Help.Json_Parse(data);
      let {src,old_src,savedir,do_ovr,do_cog,do_upload}=Json_data
      if(do_ovr){
        src=src?.replaceAll("\\","/")
        src=src?.replaceAll(global["json_config"]?.W_L?.Windows_NT,global["json_config"]?.W_L?.Linux)
        let proj_data=`${Help.Get_DirName(global["consume_exes"]["gdaladdo"])}/proj`.replaceAll("\\","/")
        let run_parmars=[
          src,
          "-r nearest",
          "--config GDAL_CACHEMAX 215",
          "--config GDAL_FILENAME_IS_UTF8 YES",
          `--config PROJ_DATA ${proj_data}`,
          "-ro --config BIGTIFF_OVERVIEW YES",
          "--config GDAL_NUM_THREADS ALL_CPUS",
        ]
        if(global["json_config"]?.show_cmd===true){
          Help.Console_log(`金字塔:${global["consume_exes"]["gdaladdo"]} ${run_parmars.join(" ")}`)
        }
        let logs="";
        let bool_result=await Help.run_exe(global["consume_exes"]["gdaladdo"],run_parmars,(_data,error)=>{
          logs=logs+_data
        })
        if(logs){
          Help.Console_log(logs)
        }
        if(bool_result){
          await Help.add_rabbitmq({
            src:src,
            old_src:old_src,
            savedir,
            do_cog,
            do_upload
          },"tif_cog")
        }
      }
      else{
        await Help.add_rabbitmq({
          src:src,
          old_src:old_src,
          savedir,
          do_cog,
          do_upload
        },"tif_cog")
      }
      
      await global["class_rabbitmq"].ack(msg)
    });
    return true
  }
  static  consume_rabbitmq_tif_cog(){
    global["class_rabbitmq"].consume("tif_cog",async (data,msg)=>{
      let Json_data=Help.Json_Parse(data);
      let {src,old_src,savedir,do_cog,do_upload}=Json_data
      if(do_cog){
        src=src?.replaceAll("\\","/")
        src=src?.replaceAll(global["json_config"]?.W_L?.Windows_NT,global["json_config"]?.W_L?.Linux)
        let denst_dir=`${global["json_config"]?.produce_base_dir}/cog`
        Help.Create_Dir(denst_dir)
        let file_name=Help.Get_FileName(src)
        savedir=savedir?.replaceAll("\\","/")
        savedir=savedir?.replaceAll(global["json_config"]?.W_L?.Windows_NT,global["json_config"]?.W_L?.Linux)
        let denst_file="";
        if(Help.Check_isdir(savedir)){
          denst_file=`${savedir}/${file_name}`.toLocaleLowerCase()
        }
        else{
          denst_file=`${denst_dir}/${file_name}`.toLocaleLowerCase()
        }
        Help.Del_File(denst_file);
        let proj_data=`${Help.Get_DirName(global["consume_exes"]["gdal_translate"])}/proj`.replaceAll("\\","/")
        let run_parmars=[
          "--config GDAL_FILENAME_IS_UTF8 YES",
          `--config PROJ_DATA ${proj_data}`,
          "-of cog",
          "-co OVERVIEW_COMPRESS=LZW",
          "-co COMPRESS=LZW",
          "-co NUM_THREADS=ALL_CPUS",
          "-co BIGTIFF=YES",
          "--config GDAL_NUM_THREADS ALL_CPUS",
          src,
          denst_file
        ]
        if(global["json_config"]?.show_cmd===true){
          Help.Console_log(`COG:${global["consume_exes"]["gdal_translate"]} ${run_parmars.join(" ")}`)
        }
        let logs="";
        let bool_result=await Help.run_exe(global["consume_exes"]["gdal_translate"],run_parmars,(_data,error)=>{
          logs=logs+_data
        })
        if(logs){
          Help.Console_log(logs)
        }
        if(bool_result){
          let ove_file=`${src}.ovr`
          Help.Del_File(src);
          Help.Del_File(ove_file);
          await Help.add_rabbitmq({
            src:denst_file,
            old_src:old_src,
            savedir,
            do_upload
          },"tif_upload")
        }
      }
      else{
        await Help.add_rabbitmq({
          src:src,
          old_src:old_src,
          savedir,
          do_upload
        },"tif_upload")
      }
      await global["class_rabbitmq"].ack(msg)
    });
  }
  static  consume_rabbitmq_tif_upload(){
    global["class_rabbitmq"].consume("tif_upload",async (data,msg)=>{
      let Json_data=Help.Json_Parse(data);
      let {src,old_src,savedir,do_upload}=Json_data
      if(do_upload){
        src=src?.replaceAll("\\","/")
        src=src?.replaceAll(global["json_config"]?.W_L?.Windows_NT,global["json_config"]?.W_L?.Linux)
        if(old_src.indexOf("s3@")>=0){
          let split_names=old_src.split("@")
          let s3_key=split_names[1]
          s3_key=s3_key.replaceAll("\\","/")
          let s3_key_splits=s3_key.split("/")
          s3_key_splits.shift()
          let s3_upload_key=s3_key_splits.join("/")
          console.log(`tif_upload: ${src} ${s3_upload_key}`)
          let s3_delete_file_result=await Help.s3_delete_file({
            bucket:global["json_config"]?.s3?.bucket,
            key:s3_upload_key,
          })
          let s3_multipartupload_file_result=false
          if(s3_delete_file_result){
            s3_multipartupload_file_result=await Help.s3_multipartupload_file({
              bucket:global["json_config"]?.s3?.bucket,
              key:s3_upload_key,
              filename:src
            })
          }
          if(s3_multipartupload_file_result){
            console.log(`tif_upload done: ${s3_upload_key}`)
            Help.Del_File(src);
          }
        }
      }
      await global["class_rabbitmq"].ack(msg)
    });
  }
  static run_exe(exec_path,parmars,cb){
    return new Promise( (resolve)=>{
      let time_tick_start=Help.Get_TimeNow()
      let options={
        shell:true, 
        detached:false,
      }
      var _spawn = spawn(exec_path, parmars, options);
      _spawn.stdout.on('data', function (data) {
        let _str_data=iconvLite.decode(data, 'cp936')
        if(typeof cb==="function"){
          cb(_str_data,null)
        }
      });
      _spawn.stderr.on('data', function (data) {
        let _str_data=iconvLite.decode(data, 'cp936')
        if(typeof cb==="function"){
          if(_str_data=="^C"){
            _str_data="用户自行关闭"
          }
          cb(_str_data,null)
        }
      });
      _spawn.on('error', function (data) {
        let _str_data=iconvLite.decode(data, 'cp936')
        if(typeof cb==="function"){
          cb(null,_str_data)
        }
      });
      _spawn.on('close', (data)=> {
        let time_tick_end=Help.Get_TimeNow()
        let time_xc=Help.Get_xc_Time(time_tick_end-time_tick_start)
        let show_tips=`耗时：${time_xc}...`
        if(data!=0){
          let errpr_tips=`不正常状态${data}`
          if(data==1){
            errpr_tips=`用户取消任务`
          }
          show_tips=`${show_tips}${errpr_tips}`
          resolve(false)
        }
        else{
          resolve(true)
        }
        Help.Console_log(`${show_tips}`,{ucolor:"yellow"});
      });
    })
  }
  static async add_rabbitmq(msg,queue,priority=50){
    let send_result=await global["class_rabbitmq"].send(queue,Help.Json_String(msg),priority);
    return send_result
  }
  static async ProcessLineByLine(_txt) {
    let lines=[]
    if(fs.existsSync(_txt)){
      const rl = readline.createInterface({
        input: fs.createReadStream(_txt),
        crlfDelay: Infinity
      });
      
      for await (const line of rl) {
        lines.push(line)
      }
    }
    return lines
  }
  static add_consume_process(){
    let fork_process_js ="";
    if(process?.env?.debugENV === 'debug'){
      fork_process_js =path.resolve("./consume_process.js");
    }
    else{
      fork_process_js =path.join(__dirname, './consume_process.js')
    }
    let one_consume_process=fork(fork_process_js);
    one_consume_process.on('close', (code, signal) => {
      Help.Console_log(`子进程 ${one_consume_process.pid}因收到信号 ${signal} 而终止,code=${code}`);
    });
    one_consume_process.on('error', (code, signal) => {
      Help.Console_log(`子进程 ${one_consume_process.pid} 出现错误`);
    });
    one_consume_process.send({
      global:{
        config:global["json_config"],
      },
      cmd:"do"
    })
    global["consume_process"]=one_consume_process
    
  }
  static Get_FileName(_file){
    let _basename=path.basename(_file);
    return _basename
  }
  static Get_DirName(_file){
    let _DirName=path.dirname(_file);
    return _DirName
  }
  static Read_File_UTF8(_file,encoding="utf-8"){
    let file_data=undefined
    if(fs.existsSync(_file)){
      try{
        file_data=fs.readFileSync(_file,{
          encoding:encoding
        })
      }
      catch(error){
      }
    }
    return file_data
  }
  static Write_File_UTF8(_file,_data){
    let is_ok=true
    try{
      fs.writeFileSync(_file,_data,{
        encoding:"utf-8"
      })
    }
    catch(error){
      is_ok=false
    }
    return is_ok
  }
  static Copy_File(_src,_dest){
    let move_status=false;
    try{
      Help.Del_File(_dest)
      fs.copyFileSync(_src,_dest)
      move_status=true;
    }
    catch(error){
      Help.Console_log(error.message)
      move_status=false
    }
    return move_status
  }
  static Move_File(_src,_dest){
    let move_status=false;
    try{
      Help.Del_File(_dest)
      fse.moveSync(_src,_dest, { overwrite: true })
      move_status=true;
    }
    catch(error){
      Help.Console_log(error.message)
      move_status=false
    }
    return move_status
  }
  static Copy_Dir(_src,_dest){
    let move_status=false;
    try{
      fse.copySync(_src,_dest)
      move_status=true;
    }
    catch(error){
      Help.Console_log(error.message)
      move_status=false
    }
    return move_status
  }
  static Move_Dir(_src,_dest){
    let move_status=false;
    try{
      fse.moveSync(_src,_dest, { overwrite: true })
      Help.Del_File_Dir(_src)
      move_status=true;
    }
    catch(error){
      Help.Console_log(error.message)
      move_status=false
    }
    return move_status
  }
  static Del_File(_src) {
    let move_status=false;
    try{
      if(Help.Check_isFile(_src)){
        fs.unlinkSync(_src)
      }
      move_status=true;
    }
    catch(error){
      move_status=false
    }
    return move_status
  }
  static Del_File_Dir(_path) {
    let move_status=false;
    try{
      fse.removeSync(_path)
      move_status=true;
    }
    catch(error){
      move_status=false
    }
    return move_status
  }
  static Create_Dir(dirfile){
    try{
      if(!Help.Check_isdir(dirfile)){
        fs.mkdirSync(dirfile,{
          recursive:true,
          mode:"07777"
        });
      }
      else{
        return true
      }
    }
    catch(error){
      return `文件夹创建失败:${error.message}`
    }
    return true
  }
  static Get_Deep_Files(_path,ext,_deep=true){
    let find_files_tifs=[]
    let all_files=fs.readdirSync(_path);
    for(let i in all_files){
      let file_name_with_ext=all_files[i]
      let file_full_name=`${_path}/${file_name_with_ext}`
      let stats=fs.statSync(file_full_name);
      if(stats.isFile()){
        let true_ext=path.extname(file_name_with_ext);
        let be_push={
          file:file_full_name.replace(/\\/g, "/"),
          name:file_name_with_ext,
          namenoext:path.basename(file_name_with_ext,true_ext),
          ext:true_ext,
          size:stats.size,
        }
        if(ext){
          if(Help.Find_ext_in_array(true_ext,ext)){
            find_files_tifs.push(be_push) 
          }
        }
        else{
          find_files_tifs.push(be_push)
        }
        
      }else{
        if(_deep){
          let _find_files_tifs=Help.Get_Deep_Files(file_full_name,ext,_deep);
          find_files_tifs=[].concat(find_files_tifs,_find_files_tifs)
        }
      }
    }
    return find_files_tifs;
  }
  static Find_ext_in_array(extname,exts){
    let ext_index=exts?.findIndex((val)=>{
      return val.toUpperCase()==extname.toUpperCase()
    })
    if(ext_index>=0){
      return true
    }
    return false
  }
  static Get_Pamars(ctx) {
    let pamars={};
    Object.assign(pamars, ctx.req.body);
    Object.assign(pamars, ctx.request.body);
    Object.assign(pamars, ctx.request.query);
    Object.assign(pamars, ctx.params);
    return pamars;
  }
  static Resolve(ctx,status=true, result=null,message='') {
    if(ctx.res){
      ctx.response.status = 200;
      ctx.body ={
        status: status,
        result: result,
        message:message
      }
    }
    else{
      return {
        status: ctx,
        result: status,
        message:result
      }
    }
  }
  static Resolve_Back(ctx,Resolve_data){
    ctx.response.status = 200;
    ctx.set("Content-Type", "application/json")
    ctx.body ={
      status: Resolve_data.status,
      result: Resolve_data.result,
      message:Resolve_data.message
    }
  }
  static Get_TimeNow(format=false){
    let date=new Date()
    if(format){
      return date.format("yyyy-MM-dd_hh_mm_ss");
    }
    else{
      return date.getTime();
    }
  }
  static Get_xc_Time(_ticks){
    let ticks = _ticks; //秒数  *1000
    let d_show ='00'
    let hour_show ='00'
    let minutes_show ='00'
    let seconds_show ='00'

    let day_ticks=24 * 60 * 60 *1000
    let hour_ticks=60 * 60 *1000;
    let minute_ticks=60 *1000;
    let second_ticks=1000;

    if(ticks>=day_ticks){
      let days = ticks / day_ticks;
      d_show = parseInt(days);//天数
      ticks = ticks - d_show * day_ticks;
    }
    if(ticks>=hour_ticks){
      let hours = ticks / hour_ticks;
      hour_show = parseInt(hours);
      ticks = ticks - hour_show *hour_ticks;
    }
    if(ticks>=minute_ticks){
      let minutes = ticks / minute_ticks;
      minutes_show = parseInt(minutes);
      ticks = ticks - minutes_show * minute_ticks;
    }
    if(ticks>=second_ticks){
      let seconds=ticks / second_ticks;
      seconds_show = parseInt(seconds);
      ticks=ticks - seconds_show *second_ticks
    }
    let no_day=`${(hour_show+"").padStart(2, ' ')}-${(minutes_show+"").padStart(2, ' ')}-${(seconds_show+"").padStart(2,' ')} ${ticks} ms`
    if(d_show>0){
      no_day=`${d_show}天 ${no_day}`
    }
    return no_day
  }
  static Console_log(log){
    if(global["json_last_msg"]!=log){
      console.log(log)
      global["json_last_msg"]=log
    }
  }
}
module.exports = Help